/*******************************************************************************
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.action;

import java.lang.reflect.InvocationTargetException;

import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.ILogEntry;
import net.sourceforge.perforce.core.api.IWhereResult;
import net.sourceforge.perforce.core.internal.P4TeamProvider;
import net.sourceforge.perforce.core.resources.RemoteFile;
import net.sourceforge.perforce.ui.internal.PerforceCompareRevisionsInput;
import net.sourceforge.perforce.ui.internal.Policy;

import org.eclipse.compare.CompareUI;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pr??mann</a>
 */
public class CompareWithRevisionAction extends PerforceAction {
  //----------------------------------------------------------------------------
  // -- Public Methods

  @Override
  public void run(IAction action) {
    final RemoteFile[] file = new RemoteFile[] {null};
    final ILogEntry[][] entries = new ILogEntry[][] {null};

    run(new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor) {
        file[0] = getSelectedRemoteFile();
      }
    }, PROGRESS_BUSYCURSOR);

    // Fetch the log entries
    run(new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor) throws InvocationTargetException {
        try {
          monitor.beginTask(Policy.bind("CompareWithRevisionAction.fetching"), 100); //$NON-NLS-1$

          entries[0] = file[0].getLogEntries(false, new SubProgressMonitor(monitor, 100));
        } catch (TeamException e) {
          throw new InvocationTargetException(e);
        } finally {
          monitor.done();
        }
      }
    }, PROGRESS_DIALOG);


    run(new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor) throws InvocationTargetException {
        try {
          IResource[] resources = getSelectedResources();
          Policy.assertTrue(resources.length == 1);

          if (!resources[0].isSynchronized(IResource.DEPTH_INFINITE)) {
            resources[0].refreshLocal(IResource.DEPTH_INFINITE, null);
          }

          CompareUI.openCompareEditor(new PerforceCompareRevisionsInput((IFile) resources[0],
              entries[0]));
        } catch (CoreException e) {
          throw new InvocationTargetException(e);
        }
      }
    }, PROGRESS_BUSYCURSOR);
  }

  // ---------------------------------------------------------------------------
  // Protected Methods

  @SuppressWarnings("unused")
  // PerforceException
  @Override
  protected boolean isEnabled() throws PerforceException {
    IResource[] resources = getSelectedResources();
    if (resources.length != 1) {
      return false;
    }

    IResource resource = resources[0];

    RepositoryProvider tempProvider = RepositoryProvider.getProvider(resource.getProject());
    if (tempProvider == null || !tempProvider.getID().equals(PerforceCorePlugin.getTypeId())) {
      return false;
    }

    P4TeamProvider provider = (P4TeamProvider) tempProvider;
    if (!(provider.hasRemote(resource))) {
      return false;
    }

    return true;
  }

  //----------------------------------------------------------------------------
  // - Private Methods

  /**
   * Call this method to retrieve the corresponding RemoteFile to the selected
   * resource.
   * 
   * @return the RemoteFile
   */
  private RemoteFile getSelectedRemoteFile() {
    IResource[] resources = getSelectedResources();
    if (resources.length != 1) {
      return null;
    }

    if (!(resources[0] instanceof IFile)) {
      return null;
    }

    IFile file = (IFile) resources[0];
    P4TeamProvider provider = P4TeamProvider.getProvider(file);
    try {
      IWhereResult whereResult = provider.getPerforceServer().where(file);
      return new RemoteFile(provider.getPerforceServer(), whereResult.getDepotFilename(), "#head"); //$NON-NLS-1$
    } catch (TeamException e) {
      handle(e);
      return null;
    }
  }
}
